package front;

import DAO.BaseDAO;
import entity.text.ChapterEntity;
import entity.text.PaperEntity;
import operation.LancetXmlFileOperation;
import operation.TextOperation;
import util.CollectionUtils;
import util.JDBCUtil;
import util.JaccardTextSimilarity;

import java.io.File;
import java.sql.Connection;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.*;

/**
 * @author ：hzs
 * @date ：Created in 2021/4/7 16:39
 * @description：
 * @modified By：
 * @version: $
 */
public class LancetCitationFront {

    private LancetXmlFileOperation lancetXmlFileOperation = new LancetXmlFileOperation();
    // 直接调用DAO层，不合规。赶时间不管了
    private BaseDAO baseDAO = new BaseDAO();
    private TextOperation textOperation = new TextOperation();
    private final String fileFormat = "D:/paper_database/Lancet0324/%s";

    public List<String> getNounsInSentence(String sentence) {
        List<String> nounPhraseFromSentence = textOperation.getNounPhraseFromSentence(sentence);
        return nounPhraseFromSentence;
    }

    public List<String> getCitationsFromFileByIndex(File file, String index) {
        try {
            List<String> citation = lancetXmlFileOperation.getCitation(file, index);
            return citation;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    public double getSimilarity(File file1, File file2) {
        try {
            PaperEntity paperEntityFromFile1 = lancetXmlFileOperation.getPaperEntityFromFile(file1);
            PaperEntity paperEntityFromFile2 = lancetXmlFileOperation.getPaperEntityFromFile(file2);
            String s1 = getContentFromPaperEntity(paperEntityFromFile1);
            String s2 = getContentFromPaperEntity(paperEntityFromFile2);
            if ("".equals(s1) || "".equals(s2)) {
                return -1.0;
            }
            return JaccardTextSimilarity.getSimilarity(s1, s2);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return -1.0;
    }

    public String getContentFromPaperEntity(PaperEntity paperEntityFromFile) {
        StringBuilder sb = new StringBuilder();
        for (ChapterEntity chapterEntity : paperEntityFromFile.getChapterEntities()) {
            sb.append(chapterEntity.getContent());
        }
        return sb.toString();
    }

    public List<List<Object>> getFileNameById(List<String> ids) {
        StringBuilder sb = new StringBuilder();
        Iterator<String> iterator = ids.iterator();
        while (iterator.hasNext()) {
            sb.append(iterator.next());
            if (iterator.hasNext()) {
                sb.append(",");
            }
        }
        String sql = "SELECT id, xmlfile FROM paper WHERE id IN (" +
                sb.toString() + ")";
        List<List<Object>> lists = baseDAO.executeReadSql(sql);
        return lists;
    }

    /**
     * 算相似度，提取引文和名词短语
     */
    public void work1() {
        String fileFormat = "D:/paper_database/Lancet0324/%s";
        LancetCitationFront lancetCitationFront = new LancetCitationFront();
        List<String> list = new ArrayList<>();
        list.add("3825");
        list.add("3788");
        list.add("3761");
        list.add("3750");
        list.add("3714");
        list.add("3665");
        List<List<Object>> fileNameById = lancetCitationFront.getFileNameById(list);
        String[] indexs = new String[]{"13", "12", "29", "4", "21"};
        for (int i = fileNameById.size()-1; i > 0; i--) {
//            String index = "13";
            // file1引用2
            File file1 = new File(String.format(fileFormat, (String)fileNameById.get(i).get(1)));
            File file2 = new File(String.format(fileFormat, (String)fileNameById.get(i-1).get(1)));
//            double similarity = lancetCitationFront.getSimilarity(file1, file2);
//            System.out.println(fileNameById.get(i).get(0).toString()
//                    + "->"
//                    + fileNameById.get(i-1).get(0).toString()
//                    + " 相似度：" + similarity);
            System.out.println(fileNameById.get(i).get(0).toString()
                    + "->"
                    + fileNameById.get(i-1).get(0).toString());
            List<String> citations = lancetCitationFront.getCitationsFromFileByIndex(file1, indexs[5-i]);
            for (String citation : citations) {
                citation = citation.replace(" +", " ");
                System.out.println(citation);
                List<String> nounsInSentence = lancetCitationFront.getNounsInSentence(citation);
                System.out.println("名词短语为：");
                for (String s : nounsInSentence) {
                    System.out.println(s);
                }
            }
        }
    }

    /**
     * 算分布率
     */
    public void work2() {
        LancetCitationFront lancetCitationFront = new LancetCitationFront();
        LancetXmlFileOperation lancetXmlFileOperation = new LancetXmlFileOperation();
        List<String> list = new ArrayList<>();
        list.add("3665");
        String words = "including members healthy".toLowerCase();
        List<List<Object>> fileNameById = lancetCitationFront.getFileNameById(list);
        File file = new File(String.format(fileFormat, (String)fileNameById.get(0).get(1)));
        PaperEntity paperEntityFromFile = null;
        try {
            paperEntityFromFile = lancetXmlFileOperation.getPaperEntityFromFile(file);
        } catch (Exception e) {
            e.printStackTrace();
        }
        List<ChapterEntity> chapterEntities = paperEntityFromFile.getChapterEntities();
        String[] split = words.split(" ");
        int count = 0;
        for (ChapterEntity chapterEntity : chapterEntities) {
            String content = chapterEntity.getContent().toLowerCase();
            int ccc = 0;
            for (String s : split) {
                if (content.contains(s)) {
                    ccc++;
                }
            }
            if (1.0 * ccc / split.length > 0.6666666667) {
                count++;
            }
        }
        System.out.println(1.0 * count / chapterEntities.size());
    }

    /**
     * 算相似度
     * @throws Exception
     */
    public void calculateSimilarity() throws Exception {
        String selectIDXmlfileSql = "(SELECT id, xmlfile FROM paper WHERE id IN (SELECT paperid FROM referencestable) ) " +
                "UNION " +
                "(SELECT id, xmlfile FROM paper WHERE id IN (SELECT referedid FROM referencestable))";
        List<List<Object>> lists = baseDAO.executeReadSql(selectIDXmlfileSql);
        Map<String, String> idFileNameMap = new HashMap<>(lists.size());
        for (List<Object> list : lists) {
            String id = list.get(0).toString();
            String xmlfile = list.get(1).toString();
            idFileNameMap.put(id, xmlfile);
        }


        String header = "UPDATE referencestable SET similarity = CASE id ";
        StringBuilder sb = new StringBuilder();
        String format = " when %d then %f ";
        String searchAllInReferenceTable = "SELECT id, paperid, referedid FROM referencestable where id <= 3000";
        lists = baseDAO.executeReadSql(searchAllInReferenceTable);
        for (List<Object> list : lists) {
            int id = (Integer)list.get(0);
            String sourceId = list.get(1).toString();
            String targetId = list.get(2).toString();
            File sourceFile = new File(String.format(fileFormat, idFileNameMap.get(sourceId)));
            File targetFile = new File(String.format(fileFormat, idFileNameMap.get(targetId)));
//            PaperEntity sourcePaper = lancetXmlFileOperation.getPaperEntityFromFile(sourceFile);
//            PaperEntity targetPaper = lancetXmlFileOperation.getPaperEntityFromFile(targetFile);
            double similarity = getSimilarity(sourceFile, targetFile);
            sb.append(String.format(format, id, similarity));
            System.out.println("id = " + id + "  similarity = " + similarity);
        }
        String sql = header.concat(sb.toString()).concat(" end where id <= 3000");
        System.out.println(sql);
        baseDAO.executeWriteSql(sql);

    }

    public void insertCitationText() throws Exception {
        String selectIDXmlfileSql = "(SELECT id, xmlfile FROM paper WHERE id IN (SELECT paperid FROM referencestable) ) " +
                "UNION " +
                "(SELECT id, xmlfile FROM paper WHERE id IN (SELECT referedid FROM referencestable))";
        List<List<Object>> lists = baseDAO.executeReadSql(selectIDXmlfileSql);
        Map<String, String> idFileNameMap = new HashMap<>(lists.size());
        for (List<Object> list : lists) {
            String id = list.get(0).toString();
            String xmlfile = list.get(1).toString();
            idFileNameMap.put(id, xmlfile);
        }

        Connection connection = JDBCUtil.getConnection();
        String header = "INSERT INTO citation_text (reference_id, citation) VALUE ";
        StringBuilder sb = new StringBuilder();
        String format = "(%d, '%s')";
        String searchAllInReferenceTable = "SELECT id, paperid, referedid, label FROM referencestable";
        lists = baseDAO.executeReadSql(searchAllInReferenceTable);
        boolean needComma = false;
        int i = 0;
        int K = 10;
        for (List<Object> list : lists) {
            int id = (Integer)list.get(0);
            String sourceId = list.get(1).toString();
            String targetId = list.get(2).toString();
            String label = list.get(3).toString().replace(".", "");
            File sourceFile = new File(String.format(fileFormat, idFileNameMap.get(sourceId)));
            File targetFile = new File(String.format(fileFormat, idFileNameMap.get(targetId)));
            List<String> citations = getCitationsFromFileByIndex(sourceFile, label);
            for (String citation : citations) {
                citation = citation.replace("\'", "\\\'").replace("\"", "\\\"");
                if (citation.length() > 1000) {
                    continue;
                }
                if (needComma) {
                    sb.append("," + String.format(format, id, citation));
                } else {
                    sb.append(String.format(format, id, citation));
                    needComma = true;
                }

                if (i++ % K == K-1) {
                    String sql = header.concat(sb.toString());
                    sb.setLength(0);
                    needComma = false;
                    try {
                        Statement statement = connection.createStatement();
                        boolean execute = statement.execute(sql);
                    } catch (SQLException e) {
                        e.printStackTrace();
                    }
                }
            }

        }
        String sql = header.concat(sb.toString());
        try {
            Statement statement = connection.createStatement();
            boolean execute = statement.execute(sql);
        } catch (SQLException e) {
            e.printStackTrace();
        }

        try {
            connection.close();
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }

    /**
     *  遍历citation_text表，抽取名词，算分布率
     */
    public void insertTableKnowledgeFlow() {
        String sql = "SELECT id, xmlfile FROM paper WHERE id IN (SELECT referedid FROM referencestable)";
        List<List<Object>> lists = baseDAO.executeReadSql(sql);
        Map<String, String> idFileNameMap = new HashMap<>(lists.size());
        for (List<Object> list : lists) {
            String id = list.get(0).toString();
            String xmlfile = list.get(1).toString();
            idFileNameMap.put(id, xmlfile);
        }

        Connection connection = JDBCUtil.getConnection();
        String header = "INSERT INTO knowledge_flow (citation_id, noun_phrase, distribution) VALUE ";
        StringBuilder sb = new StringBuilder();
        String format = "(%s, '%s', %f)";
        int i = 0;
        int K = 50;
        boolean needComma = false;
        sql = "SELECT t1.`id`, t1.`citation`, t2.`referedid` FROM citation_text t1, referencestable t2 WHERE t1.`reference_id` = t2.`id`";
        lists = baseDAO.executeReadSql(sql);
        for (List<Object> list : lists) {
            String id = list.get(0).toString();
            String citation = list.get(1).toString();
            String referedId = list.get(2).toString();

            List<String> nounsInSentence = getNounsInSentence(citation);
            File file = new File(String.format(fileFormat, idFileNameMap.get(referedId)));
            PaperEntity paperEntityFromFile = null;
            try {
                paperEntityFromFile = lancetXmlFileOperation.getPaperEntityFromFile(file);
            } catch (Exception e) {
                e.printStackTrace();
            }
            List<ChapterEntity> chapterEntities = paperEntityFromFile.getChapterEntities();
            if (CollectionUtils.isEmpty(chapterEntities)) {
                continue;
            }
            for (String noun : nounsInSentence) {
                String[] split = noun.toLowerCase().split(" ");
                int count = 0;
                for (ChapterEntity chapterEntity : chapterEntities) {
                    String content = chapterEntity.getContent().toLowerCase();
                    int ccc = 0;
                    for (String s1 : split) {
                        if (content.contains(s1)) {
                            ccc++;
                        }
                    }
                    if (1.0 * ccc / split.length > 0.6666666667) {
                        count++;
                    }
                }
                double distribution = 1.0 * count / chapterEntities.size();
                if (Double.isNaN(distribution)) {
                    continue;
                }

                noun = noun.replace("\'", "\\\'")
                        .replace("\"", "\\\"");
                if (needComma) {
                    sb.append("," + String.format(format, id, noun, distribution));
                } else {
                    sb.append(String.format(format, id, noun, distribution));
                    needComma = true;
                }
                if (i++ % K == K-1) {
                    sql = header.concat(sb.toString());
                    sb.setLength(0);
                    needComma = false;
                    try {
                        Statement statement = connection.createStatement();
                        boolean execute = statement.execute(sql);
                    } catch (SQLException e) {
                        e.printStackTrace();
                    }
                }
            }
        }

        sql = header.concat(sb.toString());
        try {
            Statement statement = connection.createStatement();
            boolean execute = statement.execute(sql);
        } catch (SQLException e) {
            e.printStackTrace();
        }

        try {
            connection.close();
        } catch (SQLException e) {
            e.printStackTrace();
        }

    }

    /**
     * 强工作流计数
     */
    public void work3() {
        String sql = "SELECT id, communityid FROM paper WHERE communityid IS NOT NULL";
//        sql = "SELECT * FROM zhanghaomima";
        List<List<Object>> lists = baseDAO.executeReadSql(sql);
        Map<String, String> map = new HashMap<>();
        for (List<Object> list : lists) {
            String id = list.get(0).toString();
            String communityId = list.get(1).toString();
            map.put(id, communityId);
        }

        sql = "SELECT t1.`paperid`, t1.`referedid` FROM referencestable t1, citation_text t2 WHERE similarity > 0.35 AND t2.`reference_id` = t1.`id` " +
                "AND t2.`id` IN (SELECT citation_id AS id FROM knowledge_flow WHERE distribution > 0.44) GROUP BY t1.`paperid`, t1.`referedid`";
        sql = "SELECT t1.`source`, t1.`target` FROM  citation_text t1 WHERE similarity > 0.295  AND deleted = 0 " +
                "AND t1.`id` IN (SELECT citation_id AS id FROM knowledge_flow WHERE distribution > 0.15) GROUP BY t1.`source`, t1.`target`";
        lists = baseDAO.executeReadSql(sql);
        Map<String, Integer> count = new HashMap<>();
        for (List<Object> list : lists) {
            String source = list.get(0).toString();
            String target = list.get(1).toString();
            String sourceCommunity = map.get(source);
            String targetCommunity = map.get(target);
            String res = sourceCommunity;
            if (!sourceCommunity.equals(targetCommunity)) {
                res = source.compareTo(target) > 0 ? source+"-"+target : target+"-"+source;
            }
            if (count.containsKey(res)) {
                count.put(res, count.get(res)+1);
            } else {
                count.put(res, 1);
            }
        }
        int kua = 0;
        int sum = 0;
        for (Map.Entry<String, Integer> entry : count.entrySet()) {
            String key = entry.getKey();
            Integer value = entry.getValue();
            sum += value;
            if (key.contains("-")) {
                kua += value;
            }
        }
        List<Map.Entry<String, Integer>> list = new ArrayList<>(count.entrySet());
        Collections.sort(list, (a, b) -> b.getValue()-a.getValue());
        System.out.println();
    }

    public static void main(String[] args) {
        LancetCitationFront lancetCitationFront = new LancetCitationFront();
        try {
            lancetCitationFront.work3();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

}
